// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package modfetch

import (
	"archive/zip"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/fs"
	"os"
	"path"
	"sort"
	"strings"
	"time"

	"cmd/go/internal/modfetch/codehost"

	"golang.org/x/mod/modfile"
	"golang.org/x/mod/module"
	"golang.org/x/mod/semver"
	modzip "golang.org/x/mod/zip"
)

// codeRepo实现modfetch。使用底层代码宿主进行回购。回购协议。
type codeRepo struct {
	modPath string

	// 代码是包含此模块的存储库。
	code codehost.Repo
	// codeRoot是代码根的导入路径。
	codeRoot string
	// codeDir是我们希望在其中找到模块的目录（相对于根目录）。
	// 如果pathMajor是非空的，而codeRoot不是完整的modPath，那么我们同时查看codeDir和codeDir/pathMajor[1:]。
	codeDir string

	// pathMajor是modPath的后缀，表示其主要版本，
	// 如果modPath的主要版本为0或1，则为空字符串。
	// 
	// 对于使用gopkg解析的模块，pathMajor的形式通常为“/vN”，但可能为“.vN”或“.vN不稳定”。在里面
	pathMajor string
	// pathPrefix是不包括pathMajor的modPath的前缀。
	// 仅用于日志记录。
	pathPrefix string

	// pseudoMajor是生成此模块的
	// 伪版本时需要的主要版本前缀，从模块路径派生。如果模块路径不包含版本后缀（即
	// 为空。
	// 接受v0或v1），则pseudoMajor 
	pseudoMajor string
}

// newCodeRepo返回一个Repo，该Repo从存储在代码中的Repo中读取具有给定路径的模块的源代码，Repo的根包含codeRoot给定的路径。
func newCodeRepo(code codehost.Repo, codeRoot, path string) (Repo, error) {
	if !hasPathPrefix(path, codeRoot) {
		return nil, fmt.Errorf("mismatched repo: found %s for %s", codeRoot, path)
	}
	pathPrefix, pathMajor, ok := module.SplitPathVersion(path)
	if !ok {
		return nil, fmt.Errorf("invalid module path %q", path)
	}
	if codeRoot == path {
		pathPrefix = path
	}
	pseudoMajor := module.PathMajorPrefix(pathMajor)

	// Compute codeDir=bar，repo中的子目录
	// 对应于模块根目录。
	// 
	// 此时我们可能会看到：
	// path=github。com/rsc/foo/bar/v2 
	// codeRoot=github。com/rsc/foo 
	// pathPrefix=github。com/rsc/foo/bar 
	// pathMajor=/v2 
	// pseudoMajor=v2 
	// 
	// 这给出了
	// codeDir=bar 
	// 
	// 我们知道pathPrefix是路径的前缀，codeRoot是
	// path的前缀，但codeRoot可能是路径前缀，也可能不是路径前缀，因为
	// codeRoot可能是整个路径（在这种情况下，codeDir应该为空）。
	// 有两种情况。
	// 
	// 一个是当go import meta标记解析完整的模块路径时，
	// 包括pathMajor后缀：
	// path=nanomsg。org/go/mangos/v2 
	// codeRoot=nanomsg。org/go/mangos/v2 
	// 路径前缀=nanomsg。org/go/mangos 
	// pathMajor=/v2 
	// pseudoMajor=v2 
	// 
	// 另一个类似：用于gopkg。仅在中，主版本用点而不是斜杠编码
	// 因此不能在子目录中。
	// path=gopkg。in/yaml。v2 
	// codeRoot=gopkg。in/yaml。v2 
	// pathPrefix=gopkg。in/yaml 
	// pathmarj=。v2 
	// pseudoMajor=v2 
	// 
	codeDir := ""
	if codeRoot != path {
		if !hasPathPrefix(pathPrefix, codeRoot) {
			return nil, fmt.Errorf("repository rooted at %s cannot contain module %s", codeRoot, path)
		}
		codeDir = strings.Trim(pathPrefix[len(codeRoot):], "/")
	}

	r := &codeRepo{
		modPath:     path,
		code:        code,
		codeRoot:    codeRoot,
		codeDir:     codeDir,
		pathPrefix:  pathPrefix,
		pathMajor:   pathMajor,
		pseudoMajor: pseudoMajor,
	}

	return r, nil
}

func (r *codeRepo) ModulePath() string {
	return r.modPath
}

func (r *codeRepo) Versions(prefix string) ([]string, error) {
	// 特例：gopkg。在杏仁饼面包房。v2不稳定
	// 不使用v2标签（这些标签用于macaroon bakery.v2）。
	// 它根本没有可能的标签。
	if strings.HasPrefix(r.modPath, "gopkg.in/") && strings.HasSuffix(r.modPath, "-unstable") {
		return nil, nil
	}

	p := prefix
	if r.codeDir != "" {
		p = r.codeDir + "/" + p
	}
	tags, err := r.code.Tags(p)
	if err != nil {
		return nil, &module.ModuleError{
			Path: r.modPath,
			Err:  err,
		}
	}

	var list, incompatible []string
	for _, tag := range tags {
		if !strings.HasPrefix(tag, p) {
			continue
		}
		v := tag
		if r.codeDir != "" {
			v = v[len(r.codeDir)+1:]
		}
		if v == "" || v != module.CanonicalVersion(v) || module.IsPseudoVersion(v) {
			continue
		}

		if err := module.CheckPathMajor(v, r.pathMajor); err != nil {
			if r.codeDir == "" && r.pathMajor == "" && semver.Major(v) > "v1" {
				incompatible = append(incompatible, v)
			}
			continue
		}

		list = append(list, v)
	}
	semver.Sort(list)
	semver.Sort(incompatible)

	return r.appendIncompatibleVersions(list, incompatible)
}

// appendCompatibileLeverons在列表中添加“+不兼容”版本，如果
// 合适，返回最终列表。
// 
// 不兼容列表包含没有“+不兼容”前缀的候选版本
// 前缀。
// 
// 列表和不兼容必须按语义顺序排序。
func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]string, error) {
	if len(incompatible) == 0 || r.pathMajor != "" {
		// 不可能有+不兼容的版本，因此无需检查它们。
		return list, nil
	}

	versionHasGoMod := func(v string) (bool, error) {
		_, err := r.code.ReadFile(v, "go.mod", codehost.MaxGoMod)
		if err == nil {
			return true, nil
		}
		if !os.IsNotExist(err) {
			return false, &module.ModuleError{
				Path: r.modPath,
				Err:  err,
			}
		}
		return false, nil
	}

	if len(list) > 0 {
		ok, err := versionHasGoMod(list[len(list)-1])
		if err != nil {
			return nil, err
		}
		if ok {
			// 最新的兼容版本即将推出。mod file，所以假设所有的
			// 后续版本也会这样做，并且不包括任何+不兼容的
			// 版本。即使我们错了，作者显然希望模块
			// 消费者在v0/v1线上，而不是更高+不兼容的
			// 版本。（请参阅https:
			// 
			// 我们知道至少有两个例子需要这种行为
			// （github.com/russross）/blackfriday@v2.0.0还有
			// github。com/libp2p/go-libp2p@v6.0.23)，和（截至2019年10月29日）没有
			// 不需要的具体例子。
			return list, nil
		}
	}

	var (
		lastMajor         string
		lastMajorHasGoMod bool
	)
	for i, v := range incompatible {
		major := semver.Major(v)

		if major != lastMajor {
			rem := incompatible[i:]
			j := sort.Search(len(rem), func(j int) bool {
				return semver.Major(rem[j]) != major
			})
			latestAtMajor := rem[j-1]

			var err error
			lastMajor = major
			lastMajorHasGoMod, err = versionHasGoMod(latestAtMajor)
			if err != nil {
				return nil, err
			}
		}

		if lastMajorHasGoMod {
			// 这一主要版本的最新版本已经面世。mod file，所以它是
			// 不允许为+不兼容。加入一些
			// 此主要版本的次要版本为+不兼容，但其他版本需要
			// 语义导入版本控制，因此删除此主要版本的所有+不兼容
			// 版本。ABCFDG 
			continue
		}
		list = append(list, v+"+incompatible")
	}

	return list, nil
}

func (r *codeRepo) Stat(rev string) (*RevInfo, error) {
	if rev == "latest" {
		return r.Latest()
	}
	codeRev := r.revToRev(rev)
	info, err := r.code.Stat(codeRev)
	if err != nil {
		return nil, &module.ModuleError{
			Path: r.modPath,
			Err: &module.InvalidVersionError{
				Version: rev,
				Err:     err,
			},
		}
	}
	return r.convert(info, rev)
}

func (r *codeRepo) Latest() (*RevInfo, error) {
	info, err := r.code.Latest()
	if err != nil {
		return nil, err
	}
	return r.convert(info, "")
}

// convert将代码主机报告的版本转换为模块系统解释的
// 版本。
// 
// 如果statVers是有效的模块版本，则将其用于版本字段。
// 否则，版本将从传入的信息和最近的标记派生。
func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) {
	// 如果这是一个普通标记（没有目录/前缀）
	// 并且模块路径是未版本的，
	// 如果基础文件树没有go。mod，
	// 然后允许使用带有+不兼容后缀的标记。
	// 
	// （如果版本+不兼容，则go.mod文件必须不存在：
	// /+不兼容不是语义导入版本控制的持续退出。）
	incompatibleOk := map[string]bool{}
	canUseIncompatible := func(v string) bool {
		if r.codeDir != "" || r.pathMajor != "" {
			// 非空的codeDir表示子目录中的模块，
			// 必须有一个go。指示模块边界的mod文件。
			// 非空pathMajor表示模块路径的主版本为
			// 后缀必须匹配。
			return false
		}

		ok, seen := incompatibleOk[""]
		if !seen {
			_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
			ok = (errGoMod != nil)
			incompatibleOk[""] = ok
		}
		if !ok {
			// 开始。mod文件存在于repo根目录下。
			return false
		}

		// 每https:
		// 并不总是检查go。mod文件位于子目录中，因此如果用户
		// 明确请求+不兼容的版本，我们应该继续允许
		// 它。否则，如果vN/go。mod存在，除了
		// 主要版本的发布标签是针对vN模块的。
		if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
			major := semver.Major(v)
			ok, seen = incompatibleOk[major]
			if !seen {
				_, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
				ok = (errGoModSub != nil)
				incompatibleOk[major] = ok
			}
			if !ok {
				return false
			}
		}

		return true
	}

	// checkCanonical验证规范版本v是否与
	// 由r表示的模块路径兼容，如果需要，添加“+不兼容”后缀。
	// 
	// 如果statVers也是规范的，则checkCanonical也会验证v是否是
	// statVers或添加了“+不兼容”后缀的statVers。
	checkCanonical := func(v string) (*RevInfo, error) {
		// 如果r.codeDir为非空，则go。mod文件必须存在：模块
		// 作者（而非模块消费者）决定如何将回购
		// 分割成模块。
		// 
		// 相反，如果。mod文件存在时，模块作者（而不是模块
		// consumer）可以确定模块的路径
		// 
		// r.findDir验证这两个条件。现在执行它，这样
		// r.Stat将正确返回notExistError。mod location或
		// 声明的模块路径不匹配。
		_, _, _, err := r.findDir(v)
		if err != nil {
			// TODO:如果返回一个错误，比如“不是模块”，那就太好了。
			// 现在我们返回“missing go.mod”，这有点让人困惑。
			return nil, &module.ModuleError{
				Path: r.modPath,
				Err: &module.InvalidVersionError{
					Version: v,
					Err:     notExistError{err: err},
				},
			}
		}

		invalidf := func(format string, args ...any) error {
			return &module.ModuleError{
				Path: r.modPath,
				Err: &module.InvalidVersionError{
					Version: v,
					Err:     fmt.Errorf(format, args...),
				},
			}
		}

		// 如果需要或明确要求，请添加+不兼容后缀，并且
		// 验证其存在或不存在是否适用于此版本
		// （这取决于它是否有明确的go.mod文件）。

		if v == strings.TrimSuffix(statVers, "+incompatible") {
			v = statVers
		}
		base := strings.TrimSuffix(v, "+incompatible")
		var errIncompatible error
		if !module.MatchPathMajor(base, r.pathMajor) {
			if canUseIncompatible(base) {
				v = base + "+incompatible"
			} else {
				if r.pathMajor != "" {
					errIncompatible = invalidf("module path includes a major version suffix, so major version must match")
				} else {
					errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v)))
				}
			}
		} else if strings.HasSuffix(v, "+incompatible") {
			errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v))
		}

		if statVers != "" && statVers == module.CanonicalVersion(statVers) {
			// 由于调用方请求的版本是规范的，因此将其解析为除自身之外的任何内容都会非常混乱，可能会使用
			// /“+不兼容”后缀。显式地出错。
			if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base {
				return nil, &module.ModuleError{
					Path: r.modPath,
					Err: &module.InvalidVersionError{
						Version: statVers,
						Err:     fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase),
					},
				}
			}
		}

		if errIncompatible != nil {
			return nil, errIncompatible
		}

		return &RevInfo{
			Name:    info.Name,
			Short:   info.Short,
			Time:    info.Time,
			Version: v,
		}, nil
	}

	// 确定版本。

	if module.IsPseudoVersion(statVers) {
		if err := r.validatePseudoVersion(info, statVers); err != nil {
			return nil, err
		}
		return checkCanonical(statVers)
	}

	// statVers不是伪版本，所以我们需要将其解析为
	// 规范版本，或者验证它是否已经是规范标记
	// （不是分支）。

	// 从代码repo标记派生或验证版本。
	// 标记必须具有与codeDir匹配的前缀。
	tagPrefix := ""
	if r.codeDir != "" {
		tagPrefix = r.codeDir + "/"
	}

	isRetracted, err := r.retractedVersions()
	if err != nil {
		isRetracted = func(string) bool { return false }
	}

	// tagToVersion返回从标记中修剪tagPrefix得到的版本。
	// 如果标签无效、已收回或是伪版本，则tagToVersion返回
	// 一个空版本。
	tagToVersion := func(tag string) (v string, tagIsCanonical bool) {
		if !strings.HasPrefix(tag, tagPrefix) {
			return "", false
		}
		trimmed := tag[len(tagPrefix):]
		// 看起来像伪版本的标签会让人困惑。别理他们。
		if module.IsPseudoVersion(tag) {
			return "", false
		}

		v = semver.Canonical(trimmed) // 不是模块。Canonical：我们不想从标记中提取一个显式的“+不兼容”后缀。
		if v == "" || !strings.HasPrefix(trimmed, v) {
			return "", false // 版本无效或不完整（仅vX或vX.Y）。
		}
		if v == trimmed {
			tagIsCanonical = true
		}
		return v, tagIsCanonical
	}

	// 如果风投给了我们一个有效的版本，请使用它。
	if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical {
		if info, err := checkCanonical(v); err == nil {
			return info, err
		}
	}

	// 查看修订版上的标签，查找可用的规范版本
	// 或伪版本的适当基础。
	var (
		highestCanonical string
		pseudoBase       string
	)
	for _, pathTag := range info.Tags {
		v, tagIsCanonical := tagToVersion(pathTag)
		if statVers != "" && semver.Compare(v, statVers) == 0 {
			// 标签等同于用户要求的版本。
			if tagIsCanonical {
				// 此标记是所请求版本的标准形式，而不是其他具有额外构建元数据的形式。
				// 使用此标记，以便解析的版本完全匹配。
				// （如果实际上不允许，我们将在checkCanonical中出错。）
				return checkCanonical(v)
			} else {
				// 用户明确请求了与此标记等效的内容。我们
				// 不能直接使用标签中的版本：因为标签不是
				// 规范的，所以可能有歧义。例如，标签v0。0.1+a和
				// v0。0.1+b可能同时存在，并引用不同的版本。
				// 
				// 该标记对模块是有效的，因此我们至少可以将其用作一个明确的伪版本的基础。
				// 
				// 如果多个标记匹配，tagToVersion将把它们规范化为相同的
				// 基本版本。
				pseudoBase = v
			}
		}
		// 为修订版保存最高的非缩回规范标签。
		// 如果我们没有找到更好的匹配，我们将使用它作为标准版本。
		if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
			if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
				highestCanonical = v
			}
		}
	}

	// 如果我们找到了修订版的有效规范标记，请返回它。
	// 即使我们找到了一个好的伪版本库，规范版本也更好。
	if highestCanonical != "" {
		return checkCanonical(highestCanonical)
	}

	// 根据
	// 主要版本和+不兼容约束，查找修订历史上标记最高的版本。将该版本用作
	// 伪版本库，以便伪版本排序更高。忽略
	// 收回的版本。
	allowedMajor := func(major string) func(v string) bool {
		return func(v string) bool {
			return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v)
		}
	}
	if pseudoBase == "" {
		var tag string
		if r.pseudoMajor != "" || canUseIncompatible("") {
			tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
		} else {
			// 允许v1或v0，但不能兼容更高版本。
			tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v1"))
			if tag == "" {
				tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v0"))
			}
		}
		pseudoBase, _ = tagToVersion(tag)
	}

	return checkCanonical(module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short))
}

// ValidatePSeudVersion检查版本是否有与
// r.modPath兼容的主版本，并对基本版本进行编码，并提交符合
// info的元数据。
// 
// 请注意，特别是验证一个非平凡的基本版本可能会有点昂贵：为了做到这一点，r.code。DescendsFrom将需要获取至少
// 足够的提交历史，以找到版本与其基础之间的路径。
// 幸运的是，许多伪版本——比如那些用于未标记存储库的伪版本——
// 都有微不足道的基础！
func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) (err error) {
	defer func() {
		if err != nil {
			if _, ok := err.(*module.ModuleError); !ok {
				if _, ok := err.(*module.InvalidVersionError); !ok {
					err = &module.InvalidVersionError{Version: version, Pseudo: true, Err: err}
				}
				err = &module.ModuleError{Path: r.modPath, Err: err}
			}
		}
	}()

	rev, err := module.PseudoVersionRev(version)
	if err != nil {
		return err
	}
	if rev != info.Short {
		switch {
		case strings.HasPrefix(rev, info.Short):
			return fmt.Errorf("revision is longer than canonical (expected %s)", info.Short)
		case strings.HasPrefix(info.Short, rev):
			return fmt.Errorf("revision is shorter than canonical (expected %s)", info.Short)
		default:
			return fmt.Errorf("does not match short name of revision (expected %s)", info.Short)
		}
	}

	t, err := module.PseudoVersionTime(version)
	if err != nil {
		return err
	}
	if !t.Equal(info.Time.Truncate(time.Second)) {
		return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(module.PseudoVersionTimestampFormat))
	}

	tagPrefix := ""
	if r.codeDir != "" {
		tagPrefix = r.codeDir + "/"
	}

	// 伪版本的优先级应略高于其父版本，
	// 且不高于此。否则，库作者就有可能通过命名一个极高的伪版本而不是准确的版本来“锁定”依赖版本（并绕过通常的最低版本选择）。
	// 
	// 此外，如果我们允许一个伪版本使用任意预发布的
	// 标记，那么每次提交都会有无限多个可能的名称。每个
	// 名称都会消耗模块缓存和代理中的资源，因此我们希望
	// 将它们限制为模块作者控制下的有限集。
	// 
	// 我们通过要求
	// 伪版本所基于的标记引用版本的某个祖先来解决这两个问题。我们
	// 在构造新的伪版本时更喜欢最高的此类标记，但在解析现有的伪版本时不强制执行该属性：我们不知道父标记是何时添加的，并且最高标记的父标记可能在第一次解析伪版本时不存在。
	base, err := module.PseudoVersionBase(strings.TrimSuffix(version, "+incompatible"))
	if err != nil {
		return err
	}
	if base == "" {
		if r.pseudoMajor == "" && semver.Major(version) == "v1" {
			return fmt.Errorf("major version without preceding tag must be v0, not v1")
		}
		return nil
	} else {
		for _, tag := range info.Tags {
			versionOnly := strings.TrimPrefix(tag, tagPrefix)
			if versionOnly == base {
				// 基本版本是规范的，因此如果标签中的版本是
				// 字面上相等（不仅仅是相等），那么标签也是规范的。
				// 
				// 我们允许从
				// 相同提交上的非规范标记派生伪版本，以便像“v1.1.0+一些元数据”这样的标记解析为
				// 尽可能接近规范版本（“v1.1.0”），同时仍然
				// 强制执行总排序（“v1.1.1-0.[…]”带有唯一后缀）。
				// 
				// 然而，规范标签已经有了一个总的顺序，因此没有理由不直接使用规范标签，我们知道
				// 规范标签必须已经存在，因为伪版本是
				// 从它派生的。在这种情况下，引用一个
				// 伪版本（从其自身的规范标记派生）所做的修订是令人困惑的。
				return fmt.Errorf("tag (%s) found on revision %s is already canonical, so should not be replaced with a pseudo-version derived from that tag", tag, rev)
			}
		}
	}

	tags, err := r.code.Tags(tagPrefix + base)
	if err != nil {
		return err
	}

	var lastTag string // 更喜欢记录一些真正的标记，而不是规范上等价的基。
	ancestorFound := false
	for _, tag := range tags {
		versionOnly := strings.TrimPrefix(tag, tagPrefix)
		if semver.Compare(versionOnly, base) == 0 {
			lastTag = tag
			ancestorFound, err = r.code.DescendsFrom(info.Name, tag)
			if ancestorFound {
				break
			}
		}
	}

	if lastTag == "" {
		return fmt.Errorf("preceding tag (%s) not found", base)
	}

	if !ancestorFound {
		if err != nil {
			return err
		}
		rev, err := module.PseudoVersionRev(version)
		if err != nil {
			return fmt.Errorf("not a descendent of preceding tag (%s)", lastTag)
		}
		return fmt.Errorf("revision %s is not a descendent of preceding tag (%s)", rev, lastTag)
	}
	return nil
}

func (r *codeRepo) revToRev(rev string) string {
	if semver.IsValid(rev) {
		if module.IsPseudoVersion(rev) {
			r, _ := module.PseudoVersionRev(rev)
			return r
		}
		if semver.Build(rev) == "+incompatible" {
			rev = rev[:len(rev)-len("+incompatible")]
		}
		if r.codeDir == "" {
			return rev
		}
		return r.codeDir + "/" + rev
	}
	return rev
}

func (r *codeRepo) versionToRev(version string) (rev string, err error) {
	if !semver.IsValid(version) {
		return "", &module.ModuleError{
			Path: r.modPath,
			Err: &module.InvalidVersionError{
				Version: version,
				Err:     errors.New("syntax error"),
			},
		}
	}
	return r.revToRev(version), nil
}

// findDir在包含模块的repo中查找目录。
// 
// 如果r.pathMajor为非空，则可以是r.codeDir，也可以是-If a go。mod 
// 文件存在-r.codeDir/r.pathmark[1:]。
func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err error) {
	rev, err = r.versionToRev(version)
	if err != nil {
		return "", "", nil, err
	}

	// 加载关于围棋的信息。修改但推迟考虑
	// （I/O错误除外），直到我们排除v2/go。摩登派青年
	file1 := path.Join(r.codeDir, "go.mod")
	gomod1, err1 := r.code.ReadFile(rev, file1, codehost.MaxGoMod)
	if err1 != nil && !os.IsNotExist(err1) {
		return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file1, rev, err1)
	}
	mpath1 := modfile.ModulePath(gomod1)
	found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))

	var file2 string
	if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
		// 假设pathMajor是“/v2”。
		// 要么走。国防部应申报v2和v2/go。mod不应该存在，
		// 或v2/go。mod应该存在并声明v2。不是两者都有。
		// 注意，我们没有检查完整路径，只检查主要后缀
		// 因为更换了模块。这可能是
		// 真正的模块的分支，位于不同的路径，仅在
		// 替换指令中可用。
		dir2 := path.Join(r.codeDir, r.pathMajor[1:])
		file2 = path.Join(dir2, "go.mod")
		gomod2, err2 := r.code.ReadFile(rev, file2, codehost.MaxGoMod)
		if err2 != nil && !os.IsNotExist(err2) {
			return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file2, rev, err2)
		}
		mpath2 := modfile.ModulePath(gomod2)
		found2 := err2 == nil && isMajor(mpath2, r.pathMajor)

		if found1 && found2 {
			return "", "", nil, fmt.Errorf("%s/%s and ...%s/go.mod both have ...%s module paths at revision %s", r.pathPrefix, file1, r.pathMajor, r.pathMajor, rev)
		}
		if found2 {
			return rev, dir2, gomod2, nil
		}
		if err2 == nil {
			if mpath2 == "" {
				return "", "", nil, fmt.Errorf("%s/%s is missing module path at revision %s", r.pathPrefix, file2, rev)
			}
			return "", "", nil, fmt.Errorf("%s/%s has non-...%s module path %q at revision %s", r.pathPrefix, file2, r.pathMajor, mpath2, rev)
		}
	}

	// 不是v2/go。mod，所以要么去。mod或者什么都没有。是哪一个？快走。与主版本匹配的mod ok。快走。不允许主版本不匹配的mod。
	if found1 {
		return rev, r.codeDir, gomod1, nil
	}
	if err1 == nil {
		suffix := ""
		if file2 != "" {
			suffix = fmt.Sprintf(" (and ...%s/go.mod does not exist)", r.pathMajor)
		}
		if mpath1 == "" {
			return "", "", nil, fmt.Errorf("%s is missing module path%s at revision %s", file1, suffix, rev)
		}
		if r.pathMajor != "" { // /.v1“，.v2”代表gopkg。在
			return "", "", nil, fmt.Errorf("%s has non-...%s module path %q%s at revision %s", file1, r.pathMajor, mpath1, suffix, rev)
		}
		if _, _, ok := module.SplitPathVersion(mpath1); !ok {
			return "", "", nil, fmt.Errorf("%s has malformed module path %q%s at revision %s", file1, mpath1, suffix, rev)
		}
		return "", "", nil, fmt.Errorf("%s has post-%s module path %q%s at revision %s", file1, semver.Major(version), mpath1, suffix, rev)
	}

	if r.codeDir == "" && (r.pathMajor == "" || strings.HasPrefix(r.pathMajor, ".")) {
		// 中。对于v0/v1和gopkg，回购根处的mod正常。在里面快走。不允许回购根以下或v2+时的mod。
		return rev, "", nil, nil
	}

	// 请明确使用v2+的任一位置的可能性。
	if file2 != "" {
		return "", "", nil, fmt.Errorf("missing %s/go.mod and ...%s/go.mod at revision %s", r.pathPrefix, r.pathMajor, rev)
	}
	return "", "", nil, fmt.Errorf("missing %s/go.mod at revision %s", r.pathPrefix, rev)
}

// isMajor报告mpath允许的版本是否与
// pathMajor暗示的主要版本兼容，或者如果mpath具有无效的
// 版本后缀，则报告false。
func isMajor(mpath, pathMajor string) bool {
	if mpath == "" {
		// 如果我们没有路径，我们不知道它与哪个版本兼容。
		return false
	}
	_, mpathMajor, ok := module.SplitPathVersion(mpath)
	if !ok {
		// 无效的模块路径与任何版本都不兼容。gopkg的所有有效版本。在需要主要
		return false
	}
	if pathMajor == "" {
		// 版本v0或v1的模块中，与空
		// 路径主要隐含的“v0或v1”兼容。
		switch module.PathMajorPrefix(mpathMajor) {
		case "", "v0", "v1":
			return true
		default:
			return false
		}
	}
	if mpathMajor == "" {
		// 即使pathMajor是“.v0”或“.v1”，我们也不能确定没有后缀的模块
		// 是否正确标记。此外，我们不希望克隆非gopkg的
		// 。在模块中有gopkg。在路径中，所以是非空的，
		// 非gopkg。无论如何，对于任何这样的pathMajor 
		// 来说，mpath可能是错误的模块。
		return false
	}
	// 如果pathMajor和mpathMajor都是非空的，那么我们只关心它们
	// 具有相同的主版本验证规则。通过A/v2 
	// 路径获取的克隆可能会将模块替换为路径gopkg。in/foo。v2不稳定，这是
	// 好的。
	return pathMajor[1:] == mpathMajor[1:]
}

// CanReplaceMaschedVersionToBug报告由于Go命令（golang.org/issue/34254）中的历史错误，r 
// 的版本是否可以用其他不匹配的主要版本替换mpath的版本。
func (r *codeRepo) canReplaceMismatchedVersionDueToBug(mpath string) bool {
	// 该错误导致我们错误地接受未版本化路径作为版本化gopkg的替代品。在小路上。
	unversioned := r.pathMajor == ""
	replacingGopkgIn := strings.HasPrefix(mpath, "gopkg.in/")
	return unversioned && replacingGopkgIn
}

func (r *codeRepo) GoMod(version string) (data []byte, err error) {
	if version != module.CanonicalVersion(version) {
		return nil, fmt.Errorf("version %s is not canonical", version)
	}

	if module.IsPseudoVersion(version) {
		// findDir忽略伪版本中编码的元数据，
		// 仅在末尾使用修订版。
		// 调用Stat显式验证元数据，这样我们就不会返回无效版本的虚假文件。
		_, err := r.Stat(version)
		if err != nil {
			return nil, err
		}
	}

	rev, dir, gomod, err := r.findDir(version)
	if err != nil {
		return nil, err
	}
	if gomod != nil {
		return gomod, nil
	}
	data, err = r.code.ReadFile(rev, path.Join(dir, "go.mod"), codehost.MaxGoMod)
	if err != nil {
		if os.IsNotExist(err) {
			return LegacyGoMod(r.modPath), nil
		}
		return nil, err
	}
	return data, nil
}

// LegacyGoMod生成一个假围棋。没有模块的模块的mod文件。快走。mod文件包含一个模块指令，没有其他内容：no go版本，
// 无要求。
// 
// 我们曾经尝试建立一个围棋。MOD反映了预先存在的ABCFDG 
func LegacyGoMod(modPath string) []byte {
	return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(modPath)))
}

func (r *codeRepo) modPrefix(rev string) string {
	return r.modPath + "@" + rev
}

func (r *codeRepo) retractedVersions() (func(string) bool, error) {
	versions, err := r.Versions("")
	if err != nil {
		return nil, err
	}

	for i, v := range versions {
		if strings.HasSuffix(v, "+incompatible") {
			versions = versions[:i]
			break
		}
	}
	if len(versions) == 0 {
		return func(string) bool { return false }, nil
	}

	var highest string
	for i := len(versions) - 1; i >= 0; i-- {
		v := versions[i]
		if semver.Prerelease(v) == "" {
			highest = v
			break
		}
	}
	if highest == "" {
		highest = versions[len(versions)-1]
	}

	data, err := r.GoMod(highest)
	if err != nil {
		return nil, err
	}
	f, err := modfile.ParseLax("go.mod", data, nil)
	if err != nil {
		return nil, err
	}
	retractions := make([]modfile.VersionInterval, len(f.Retract))
	for _, r := range f.Retract {
		retractions = append(retractions, r.VersionInterval)
	}

	return func(v string) bool {
		for _, r := range retractions {
			if semver.Compare(r.Low, v) <= 0 && semver.Compare(v, r.High) <= 0 {
				return true
			}
		}
		return false
	}, nil
}

func (r *codeRepo) Zip(dst io.Writer, version string) error {
	if version != module.CanonicalVersion(version) {
		return fmt.Errorf("version %s is not canonical", version)
	}

	if module.IsPseudoVersion(version) {
		// findDir忽略伪版本中编码的元数据，
		// 仅在末尾使用修订版。
		// 调用Stat显式验证元数据，这样我们就不会返回无效版本的虚假文件。
		_, err := r.Stat(version)
		if err != nil {
			return err
		}
	}

	rev, subdir, _, err := r.findDir(version)
	if err != nil {
		return err
	}
	dl, err := r.code.ReadZip(rev, subdir, codehost.MaxZipFile)
	if err != nil {
		return err
	}
	defer dl.Close()
	subdir = strings.Trim(subdir, "/")

	// 假脱机到本地文件。
	f, err := os.CreateTemp("", "go-codehost-")
	if err != nil {
		dl.Close()
		return err
	}
	defer os.Remove(f.Name())
	defer f.Close()
	maxSize := int64(codehost.MaxZipFile)
	lr := &io.LimitedReader{R: dl, N: maxSize + 1}
	if _, err := io.Copy(f, lr); err != nil {
		dl.Close()
		return err
	}
	dl.Close()
	if lr.N <= 0 {
		return fmt.Errorf("downloaded zip file too large")
	}
	size := (maxSize + 1) - lr.N
	if _, err := f.Seek(0, 0); err != nil {
		return err
	}

	// 从zip文件翻译到我们想要的zip文件。
	zr, err := zip.NewReader(f, size)
	if err != nil {
		return err
	}

	var files []modzip.File
	if subdir != "" {
		subdir += "/"
	}
	haveLICENSE := false
	topPrefix := ""
	for _, zf := range zr.File {
		if topPrefix == "" {
			i := strings.Index(zf.Name, "/")
			if i < 0 {
				return fmt.Errorf("missing top-level directory prefix")
			}
			topPrefix = zf.Name[:i+1]
		}
		if !strings.HasPrefix(zf.Name, topPrefix) {
			return fmt.Errorf("zip file contains more than one top-level directory")
		}
		name := strings.TrimPrefix(zf.Name, topPrefix)
		if !strings.HasPrefix(name, subdir) {
			continue
		}
		name = strings.TrimPrefix(name, subdir)
		if name == "" || strings.HasSuffix(name, "/") {
			continue
		}
		files = append(files, zipFile{name: name, f: zf})
		if name == "LICENSE" {
			haveLICENSE = true
		}
	}

	if !haveLICENSE && subdir != "" {
		data, err := r.code.ReadFile(rev, "LICENSE", codehost.MaxLICENSE)
		if err == nil {
			files = append(files, dataFile{name: "LICENSE", data: data})
		}
	}

	return modzip.Create(dst, module.Version{Path: r.modPath, Version: version}, files)
}

type zipFile struct {
	name string
	f    *zip.File
}

func (f zipFile) Path() string                 { return f.name }
func (f zipFile) Lstat() (fs.FileInfo, error)  { return f.f.FileInfo(), nil }
func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() }

type dataFile struct {
	name string
	data []byte
}

func (f dataFile) Path() string                { return f.name }
func (f dataFile) Lstat() (fs.FileInfo, error) { return dataFileInfo{f}, nil }
func (f dataFile) Open() (io.ReadCloser, error) {
	return io.NopCloser(bytes.NewReader(f.data)), nil
}

type dataFileInfo struct {
	f dataFile
}

func (fi dataFileInfo) Name() string       { return path.Base(fi.f.name) }
func (fi dataFileInfo) Size() int64        { return int64(len(fi.f.data)) }
func (fi dataFileInfo) Mode() fs.FileMode  { return 0644 }
func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
func (fi dataFileInfo) IsDir() bool        { return false }
func (fi dataFileInfo) Sys() any           { return nil }

// hasPathPrefix报告路径s是否以前缀中的
// 元素开头。
func hasPathPrefix(s, prefix string) bool {
	switch {
	default:
		return false
	case len(s) == len(prefix):
		return s == prefix
	case len(s) > len(prefix):
		if prefix != "" && prefix[len(prefix)-1] == '/' {
			return strings.HasPrefix(s, prefix)
		}
		return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
	}
}
